package com.app.core.web.filter;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.app.core.common.AppCons;
import com.app.core.common.Result;
import com.app.core.common.ResultCode;
import com.app.core.session.UserSession;
import com.app.core.web.context.RequestContext;
import com.app.core.web.util.AppContextUtil;

/**
 * 登录过滤器
 * 
 * @author zhangxf
 * @created 2017年4月16日 下午12:00:52
 */
public class LoginFilter implements Filter {

    @SuppressWarnings("unused")
    private static final Logger log = LoggerFactory.getLogger(LoginFilter.class);

    private static Map<String, String> noFilterMap = new HashMap<String, String>();

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        /* 初始化不需要拦截的url */
        String noFilter = filterConfig.getInitParameter("noFilter");
        if (StringUtils.isNotBlank(noFilter)) {
            String[] split = noFilter.split(",");
            for (String s : split) {
                noFilterMap.put(s, s);
            }
        }
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain)
        throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;

        /* 解析请求的URL */
        String contextPath = request.getContextPath();
        String requestURI = request.getRequestURI();
        requestURI = requestURI.substring(contextPath.length(), requestURI.length());
        requestURI = requestURI.split("\\?")[0];

        /* 不需要拦截的直接放行 */
        if (noFilterMap.containsKey(requestURI)) {
            chain.doFilter(servletRequest, servletResponse);
            return;
        }

        /* 获取用户登录token */
        String token = request.getParameter("token");
        if (StringUtils.isBlank(token)) {
            token = (String) request.getAttribute("token");
        }

        /* 若token为空，返回登录 */
        if (StringUtils.isBlank(token)) {
            jsonLogin(request, response, Result.error(ResultCode.SESSION_EXPIRE).toJson());
            return;
        }

        /* 获取session */
        UserSession userSession = (UserSession) AppContextUtil.getSessionValue(token);

        /* 若session为空，返回登录 */
        if (userSession == null) {
            jsonLogin(request, response, Result.error(ResultCode.SESSION_EXPIRE).toJson());
            return;
        }

        /* session存在 */
        try {
            // 刷新session失效时间
            AppContextUtil.refreshSession(token, AppCons.USER_SESSION_TIMEOUT);
            // 设置RequestContext
            RequestContext.setUserSession(userSession);
            RequestContext.setUserId(userSession.getUserId());
            RequestContext.setLoginUserId(userSession.getUserId());
            RequestContext.setLoginUserName(userSession.getLoginName());

            request.setAttribute("userSession", userSession);

            chain.doFilter(servletRequest, servletResponse);

        } finally {
            /* 切记！一定要清除线程变量 */
            RequestContext.clearVariable();
        }
    }

    public void redirectLogin(HttpServletRequest request, HttpServletResponse response, String msg)
        throws IOException, ServletException {
        String requestedWith = request.getHeader("x-requested-with");
        // ajax请求
        if (requestedWith != null && "XMLHttpRequest".equals(requestedWith)) {
            jsonLogin(request, response, msg);
            return;
        } else {
            if (msg == null) {
                response.sendRedirect(request.getContextPath() + request.getServletPath() + "/login");
            } else {
                response.sendRedirect(request.getContextPath() + request.getServletPath() + "/login?error=" + msg);
            }
            return;
        }
    }

    public void jsonLogin(HttpServletRequest request, HttpServletResponse response, String msg) throws IOException {
        response.setCharacterEncoding("UTF-8");
        response.setHeader("content-type", "application/json;charset=UTF-8");
        PrintWriter out = response.getWriter();
        out.print(msg);
        out.flush();
    }

    @Override
    public void destroy() {
    }
}
